package com.tedu.api.list;

import org.junit.Test;

import javax.swing.text.html.HTMLDocument;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * 迭代器：打印集合的元素【接口】
 * 集合提供自己的一套输出集合元素方法---迭代器【类似for、增强for】
 * 包位置：java.util
 * Iterator 接口
 * 该接口是集合接口，提供遍历元素的相关操作：问、取、删
 * iterator（）方法  返回值Iterator   ----Collection接口类已经存在方法
 * 作用：获取一个用于遍历当前集合迭代器的实现类实例
 * <p>
 * 遍历规则：问、取、删（删不是必须操作）
 */
public class Collection_iterator {
    @Test
    public void testIterator() {
        //创建集合
        Collection c1 = new ArrayList();
        c1.add("one");
        c1.add("two");
        c1.add("three");
        c1.add("four");
        c1.add("five");
        c1.add("six");
        //iterator（）获取一个用于遍历当前集合迭代器的实现类实例
        Iterator it = c1.iterator();
        //理解：拿到集合中所有的元素，封装迭代器的创建对象过程--理解迭代器的实例
        //使用Iterator---获取集合的某个元素，规则：问、取、删
        //Iterator接口----hasNest（）获取集合元素
        //思考：如果说，300个元素  ---循环  while  次数不固定
        while (it.hasNext()) {
            //①问：集合是否有元素呢？
            //迭代器集合：获取元素  next（）获取元素   返回值Object
            String str = (String) it.next();   //②取：获取集合元素
            System.out.println("迭代器" + str);
        }
        //迭代器是否改变集合的元素内容
        System.out.println(c1);
    }

    /**
     * 试试
     * 普通for--遍历c1集合
     * 增强for--遍历c1集合
     * Iterator迭代器--集合提供接口
     */
    @Test
    public void testCollection() {
        Collection c1 = new ArrayList();
        c1.add("one");
        c1.add("two");
        c1.add("three");
        c1.add("four");
        c1.add("five");
        c1.add("six");
        for (int i = 0; i < c1.size(); i++) {
            System.out.println(c1.toArray()[i]);
        }
        for (Object c : c1) {
            System.out.println(c);
        }
    }

    /**
     * remove()  删除  Iterator迭代器   增强for
     * 作用：删除获取到的元素数据，提醒：问  取next方法  【删】
     */
    @Test
    public void testRemove() {
        Collection c = new ArrayList();
        c.add("西游记");
        c.add("#");
        c.add("水浒传");
        //需求：通过迭代器删除#
        Iterator it = c.iterator();
        while (it.hasNext()) {
            //问：有没有代码
            String str = (String) it.next();  // 取：有元素---打印元素
            // c.remove("#"); //Collection中存在remove（）
            //删除一定是迭代器
            if ("#".equals(str)) {
                //如果#是我们拿到的str元素中的#
                it.remove();   //那么就删除元素
            }
        }
        System.out.println("迭代器删除：" + c);
    }

    /**
     * 增强for--底层使用Iterator迭代器【问  取  删】
     * c.remove("#")是Collection的删除方法，并不是迭代器方法
     * 需求：删除集合当中元素是“#”的
     */
    @Test
    public void testFor() {
        Collection c = new ArrayList();
        c.add("西游记");
        c.add("#");
        c.add("水浒传");
        for (Object o : c) {
            //类型  类型引用：集合引用
            String str = (String) o;     //强转：拿到字符串类型
            //if ("#".equals(str)){
            c.remove("#");
            //}
        }
        System.out.println("删除集合元素：" + c);
    }

    /**
     * E      element   泛型  JDK1.5后新特性
     * 结合集合出现，约束集合的使用的类型【基本数据类型，引用类型，包装类】
     * 泛型的原型：Object，泛型是编译器认可的，JVM虚拟机并不认可
     * 使用泛型是告诉编译器应该把泛型当成Object类型执行，便于编译器检查
     * 类型以及自动造型操作
     * <p>
     * JDK1.5泛型使用：
     * Collection<类型：基本类型，引用类型，包装类>
     * c=new ArrayLis<类型：基本类型，引用类型，包装类>（）;
     * <p>
     * JDK1.7泛型使用：
     * Collection<类型：基本类型，引用类型，包装类>
     * c=new ArrayList<>();
     * <p>
     * 泛型：自动推导            同配符： ？ 表示任意类型
     * Collection<类型：？>
     * c=new ArrayList<>();
     * <p>
     * Collection<类型：？ extends/super    父类/接口/类>
     * c=new ArrayList<>();
     * 优点：保证类型安全，提高代码重用性和灵活性
     * 上限：限定集合传入对应类型
     */
    @Test
    public void testType() {
        //针对泛型自动推导     通配符 ？
        Collection<?> c1 = new ArrayList<>();
        //c1.add(1);
        //c1.add("1");
        //c1.add(new Object());
        c1.add(null);   //结论：并不是匹配所有类型，只能传null，没有意义


        Collection<String> c = new ArrayList<String>();
        c.add("123");
        c.add("456");
        c.add("789");
        //遍历Iterator
        Iterator<String> it = c.iterator();
        while (it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }
    }
}


//----限定集合传入对应类型
class Fruit {
    private String name;  //成员变量

    public Fruit(String name) {
        //有参构造器
        this.name = name;
    }

    public String getName() {
        //方法
        return name;
    }
}

class Apple extends Fruit {
    public Apple() {
        //调用父类有参构造器，传入name名称
        super("苹果");
    }
}

class Orange extends Fruit {
    public Orange() {
        //调用父类有参构造器，传入name名称
        super("橘子");
    }
}

//测试类----泛型上界
class TestJob {
    //泛型上界 1.定义方法，制定泛型规则--集合中类型约定为Apple与Orange
    public static void printFruit(Collection<? extends Fruit> fruits) {
        //2.增强for循环打印，，集合中类型约定为Apple与Orange
        for (Fruit fruit : fruits) {
            //3.方法能进入： Apple或Orange---打印名字
            System.out.println(fruit.getName());
        }
    }

    public static void main(String[] args) {
        Collection<Apple> apples = new ArrayList<>();
        apples.add(new Apple());    //集合对象添加：Apple对象
        Collection<Orange> oranges=new ArrayList<>();
        oranges.add(new Orange());   //集合对象添加：Orange对象
        printFruit(apples);     //测试打印出苹果
        printFruit(oranges);
        //假设：西瓜
        //Collection<String> strings=new ArrayList<>();
        //strings.add(new String());
        //printFruit(strings);

    }
}

